import mongoose, { Schema } from 'mongoose';
import _ from 'lodash';
import channelHandlers from '../handler/channelHandlers';

const schema = new Schema(
  {
    name: { type: String, unique: true, index: true },
    topic: { type: String },
    purpose: { type: String },
    isPrivate: { type: Boolean, default: false },
    customer: { type: Schema.Types.ObjectId, ref: 'User', index: true },
    group: { type: Schema.Types.ObjectId, ref: 'Group' },
    creator: { type: Schema.Types.ObjectId, ref: 'User' },
    admins: [{ type: Schema.Types.ObjectId, ref: 'User' }],
    members: [{ type: Schema.Types.ObjectId, ref: 'User' }],
    createdAt: { type: Date, default: Date.now },
    lastActiveAt: { type: Date, default: Date.now },
    lastCustomerMessage: { type: Schema.Types.ObjectId, ref: 'Message' },
  },
  {
    collection: 'channels',
  },
);

/**
 * Instance Methods------------------------------------------------
 */
schema.methods.getChannelUser = async function getChannelUser(user) {
  const ChannelUserModel = mongoose.model('ChannelUser');

  return ChannelUserModel.findOne({ channel: this, user });
};

schema.methods.inviteByUserIds = async function inviteByUserIds(userIds) {
  if (!userIds) return Promise.resolve();

  const UserModel = mongoose.model('User');
  const flattenUserIds = _.flatten([userIds]);

  return Promise.all(flattenUserIds.map(userId => UserModel.findById(userId))).then((users) => {
    users.filter(Boolean).forEach(u => this.addMember(u));
  });
};

schema.methods.addMember = async function addMember(user) {
  return channelHandlers.join(this, user);
};

schema.methods.getBasicInfo = function getBasicInfo() {
  return {
    id: this.id,
    name: this.name,
    isPrivate: this.isPrivate,
    members: this.members,
  };
};

schema.methods.getRedisChannelName = function getRedisChannelName() {
  return `channel:${this.id}`;
};

// 判定一个用户，是否有响应组在其中
schema.methods.isInService = async function isInService(user) {
  await this.populate('group').execPopulate();
  await this.populate({
    path: 'members',
    select: '_id username nickname isRobot group',
  }).execPopulate();

  const responseGroups = this.group.responseGroups.map(groupId => groupId.toString());
  const memberGroups = this.members
    .filter(member =>
      // robot没有所属组
      member.group && member.id !== user.id)
    .map(member => member.group.toString());

  // 响应组组和成员组间存在交集
  return _.intersection(responseGroups, memberGroups).length > 0;
};

export default mongoose.model('Channel', schema);
